package com.atguigu.schedule.service.impl;

import com.atguigu.schedule.service.FileConversionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * 文件转换服务实现
 */
@Service
@Slf4j
public class FileConversionServiceImpl implements FileConversionService {
    
    @Value("${recording.output-path:/recordings}")
    private String outputPath;
    
    @Override
    public String convertTmpToMp4(String tmpFilePath) {
        try {
            File tmpFile = new File(tmpFilePath);
            if (!tmpFile.exists()) {
                log.warn("临时文件不存在: {}", tmpFilePath);
                return null;
            }
            
            // 生成目标文件路径（去掉.tmp后缀）
            String targetPath = tmpFilePath.replace(".mp4.tmp", ".mp4");
            File targetFile = new File(targetPath);
            
            // 如果目标文件已存在，先删除
            if (targetFile.exists()) {
                if (targetFile.delete()) {
                    log.info("删除已存在的目标文件: {}", targetPath);
                } else {
                    log.warn("无法删除已存在的目标文件: {}", targetPath);
                }
            }
            
            // 重命名文件
            boolean success = tmpFile.renameTo(targetFile);
            if (success) {
                log.info("文件转换成功: {} -> {}", tmpFilePath, targetPath);
                return targetPath;
            } else {
                log.error("文件重命名失败: {} -> {}", tmpFilePath, targetPath);
                return null;
            }
            
        } catch (Exception e) {
            log.error("转换文件失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public List<String> batchConvertTmpFiles(String directoryPath) {
        List<String> convertedFiles = new ArrayList<>();
        
        try {
            List<File> tmpFiles = getTmpFiles(directoryPath);
            log.info("找到 {} 个mp4.tmp文件需要转换", tmpFiles.size());
            
            for (File tmpFile : tmpFiles) {
                String convertedPath = convertTmpToMp4(tmpFile.getAbsolutePath());
                if (convertedPath != null) {
                    convertedFiles.add(convertedPath);
                }
            }
            
            log.info("批量转换完成，成功转换 {} 个文件", convertedFiles.size());
            
        } catch (Exception e) {
            log.error("批量转换文件失败: {}", e.getMessage(), e);
        }
        
        return convertedFiles;
    }
    
    @Override
    public String fixRecordingFileFormat(Long recordingId) {
        try {
            // 查找可能的临时文件
            List<File> tmpFiles = getTmpFiles(outputPath);
            
            for (File tmpFile : tmpFiles) {
                String fileName = tmpFile.getName();
                // 检查文件名是否包含录制ID
                if (fileName.contains(recordingId.toString())) {
                    log.info("找到录制ID {} 对应的临时文件: {}", recordingId, fileName);
                    return convertTmpToMp4(tmpFile.getAbsolutePath());
                }
            }
            
            log.warn("未找到录制ID {} 对应的临时文件", recordingId);
            return null;
            
        } catch (Exception e) {
            log.error("修复录制文件格式失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public List<File> getTmpFiles(String directoryPath) {
        List<File> tmpFiles = new ArrayList<>();
        
        try {
            Path dir = Paths.get(directoryPath);
            if (!Files.exists(dir) || !Files.isDirectory(dir)) {
                log.warn("目录不存在或不是目录: {}", directoryPath);
                return tmpFiles;
            }
            
            try (Stream<Path> paths = Files.walk(dir)) {
                paths.filter(Files::isRegularFile)
                     .filter(path -> path.toString().endsWith(".mp4.tmp"))
                     .forEach(path -> tmpFiles.add(path.toFile()));
            }
            
            log.info("在目录 {} 中找到 {} 个mp4.tmp文件", directoryPath, tmpFiles.size());
            
        } catch (IOException e) {
            log.error("扫描目录失败: {}", e.getMessage(), e);
        }
        
        return tmpFiles;
    }
    
    /**
     * 使用FFmpeg重新编码文件（如果需要）
     */
    public String reencodeWithFFmpeg(String inputPath, String outputPath) {
        try {
            // 构建FFmpeg命令
            String command = String.format(
                "ffmpeg -i \"%s\" -c:v libx264 -c:a aac -preset fast -crf 23 \"%s\"",
                inputPath, outputPath
            );
            
            log.info("执行FFmpeg重新编码命令: {}", command);
            
            ProcessBuilder processBuilder = new ProcessBuilder();
            if (System.getProperty("os.name").toLowerCase().contains("windows")) {
                processBuilder.command("cmd", "/c", command);
            } else {
                processBuilder.command("sh", "-c", command);
            }
            
            Process process = processBuilder.start();
            int exitCode = process.waitFor();
            
            if (exitCode == 0) {
                log.info("FFmpeg重新编码成功: {} -> {}", inputPath, outputPath);
                return outputPath;
            } else {
                log.error("FFmpeg重新编码失败，退出码: {}", exitCode);
                return null;
            }
            
        } catch (Exception e) {
            log.error("FFmpeg重新编码异常: {}", e.getMessage(), e);
            return null;
        }
    }
}
